#pragma once

#include <unistd.h>
#include <cassert>
#include <iostream>
#include <typeinfo>
#include <algorithm>

class Holder
{
public:
    Holder() {};
    virtual ~Holder() {};
    //获取当前存储数据的类型
    virtual const std::type_info& GetType() = 0;
    //获取一个与当前保存数据相同的对象 -> 深拷贝
    virtual Holder* clone() = 0;
};

template<class T>
class PlaceHolder : public Holder
{
public:
    PlaceHolder(const T& val)
        :_val(val)
    {}
    
    virtual ~PlaceHolder() {}

    virtual const std::type_info& GetType()
    {
        //typeid 是一个运算符
        return typeid(T);
    }

    virtual Holder* clone()
    {
        return new PlaceHolder(_val);
    }

public:
    T _val;
};


class Any
{
public:
    //空构造
    Any() :_content(nullptr) {}

    ~Any() { delete _content; }

    template<class T>
    Any(const T& val)
        :_content(new PlaceHolder<T>(val))
    { }

    Any(const Any& other)
        //如果当前存储的数据不为空，则进行一次clone
        :_content(other._content != nullptr ? (other._content)->clone() : nullptr)
    { }

    Any& Swap(Any& other)
    {
        std::swap(_content, other._content);
        return *this;
    }

    template<class T>
    Any& operator=(const T& val)
    {
        //构造临时对象并交换
        Any(val).Swap(*this);
        return *this;
    }

    Any& operator=(const Any& other)
    {
        //构造临时对象并交换，不影响原other对象
        Any(other).Swap(*this);
        return *this;
    }
    //获取当前保存值的指针
    template<class T>
    T* Get()
    {
        assert(typeid(T) == typeid(((PlaceHolder<T>*)_content)->_val));
        return &(((PlaceHolder<T>*)_content)->_val);
    }

private:
    Holder* _content;
};